#include "TimerChannel.h"
#include <sys/socket.h>
#include <sys/uio.h>  // readv
#include <unistd.h>
#include <sys/timerfd.h>
#include"Logger.h"
using namespace Log;

namespace wjc {
	TimerChannel::TimerChannel(Core* core, int64_t interval_ms) :
		core_(core),
		timerfd_(createTimerfd()),
		channel_(new Channel(core, timerfd_)),
		interval_ms_(interval_ms),
		start_(false)
	{
		channel_->setReadCallback(std::bind(&TimerChannel::handleRead, this));

	}
	TimerChannel::~TimerChannel() {
		assert(channel_->isNoneEvent());
	}
	void TimerChannel::handleRead() {
		uint64_t howmany;
		ssize_t n = ::read(timerfd_, &howmany, sizeof howmany);
		Timestamp now= Timestamp::now();
		LOG_TRACE << "TimerChannel::handleRead() " << howmany << " at " << now.toString();
		if (n != sizeof howmany)
		{
			LOG_ERROR << "TimerChannel::handleRead() reads " << n << " bytes instead of 8";
		}
		if (onTimer_)
			onTimer_();
	}


	int TimerChannel::createTimerfd()
	{
		int timerfd = ::timerfd_create(CLOCK_MONOTONIC,
			TFD_NONBLOCK | TFD_CLOEXEC);

		if (timerfd < 0)
		{
			LOG_SYSFATAL << "Failed in timerfd_create";
		}
		return timerfd;
	}

	void TimerChannel::resetTimerfd(int timerfd, int64_t interval_ms)
	{
		// wake up loop by timerfd_settime()
		struct itimerspec newValue;
		struct itimerspec oldValue;
		struct timespec ts;
		ts.tv_sec = interval_ms / 1000;
		ts.tv_nsec = (interval_ms % 1000) * 1000;
		newValue.it_value = ts;
		newValue.it_interval = ts;
		int ret = ::timerfd_settime(timerfd, 0, &newValue, &oldValue);
		if (ret)
		{
			LOG_SYSERR << "timerfd_settime()";
		}
	}


}